/*
	Leola Programming Language
	Author: Tony Sparks
	See license.txt
*/
package leola.vm.types;

import java.io.DataOutput;
import java.io.IOException;

import leola.vm.Leola;
import leola.vm.asm.Bytecode;
import leola.vm.asm.Outer;
import leola.vm.asm.Scope;


/**
 * Defines a namespace.
 *
 * @author Tony
 *
 */
public class LeoNamespace extends LeoScopedObject {

	/**
	 * The namespaces name
	 */
	private String name;

	/**
	 * @param scope
	 * @param name
	 */
	public LeoNamespace(Scope scope, String name) {
		this(null, null, scope, name);
	}

	/**
	 * @param runtime
	 * @param code
	 * @param scope
	 * @param name
	 */
	public LeoNamespace(Leola runtime, Bytecode code, Scope scope, String name) {
		super(LeoType.NAMESPACE, scope, (code !=null ) ? code.numOuters : 0);

		this.name = name;
		
		addProperty(LeoString.valueOf("this"), this);		
		
		// NOTE, we can't execute the bytecode here because
		// the outers will not be set at this point
//		if ( code != null && runtime != null ) {
//			runtime.execute(this, code);
//		}
	}
	
	/* (non-Javadoc)
	 * @see leola.vm.types.LeoObject#toString()
	 */
	@Override
	public String toString() {	
		return String.format("[ %s @ %s ]", this.getType(), this.name);
	}
	
	/**
	 * @return the name
	 */
	public String getName() {
		return name;
	}
	
	/* (non-Javadoc)
	 * @see leola.vm.types.LeoObject#isNamespace()
	 */
	@Override
	public boolean isNamespace() {	
		return true;
	}

	/**
	 * Overrides the previous outers
	 * @param outers
	 */
	public void setOuters(Outer[] outers) {
		this.outers = outers;
	}

	/* (non-Javadoc)
	 * @see leola.vm.types.LeoObject#add(leola.vm.types.LeoObject)
	 */
	@Override
	public LeoObject $add(LeoObject other) {
		if (other.isString()) {
			return LeoString.valueOf(toString() + other.toString());
		}
		return super.$add(other);
	}

	/* (non-Javadoc)
	 * @see leola.types.LeoObject#eq(leola.types.LeoObject)
	 */
	@Override
	public boolean $eq(LeoObject other) {
		boolean isEquals = (other == this);

		if ( !isEquals && other != null ) {
			if ( other.isOfType(LeoType.NAMESPACE)) {
				LeoNamespace ns = other.as();
				isEquals = this.name.equals(ns.name);
			}
		}

		return isEquals;
	}

	/* (non-Javadoc)
	 * @see leola.types.LeoObject#gt(leola.types.LeoObject)
	 */
	@Override
	public boolean $gt(LeoObject other) {
		return false;
	}

	/* (non-Javadoc)
	 * @see leola.types.LeoObject#lt(leola.types.LeoObject)
	 */
	@Override
	public boolean $lt(LeoObject other) {
		return false;
	}

	/* (non-Javadoc)
	 * @see leola.types.LeoObject#getValue()
	 */
	@Override
	public Object getValue() {
		return this;
	}
	
	/* (non-Javadoc)
	 * @see leola.types.LeoObject#clone()
	 */
	@Override
	public LeoObject clone() {			
		return this;
	}

	/* (non-Javadoc)
	 * @see leola.vm.types.LeoObject#write(java.io.DataOutput)
	 */
	@Override
	public void write(DataOutput out) throws IOException {		
	}
}

